package baseStructure;

/***
 * @author Ragnvald Fuglestein
 */

import java.io.Serializable;
import java.util.List;

@SuppressWarnings("rawtypes")
public class SortedList<E extends Comparable> extends BaseList<E> implements Serializable {
	private static final long serialVersionUID = -7026466417825174873L;

	public SortedList() {
		super();
	}
	
	public SortedList(int s) throws IllegalArgumentException {
		super(s);
	}
	
	public SortedList(int s, int g) throws IllegalArgumentException {
		super(s, g);
	}

	@SuppressWarnings("unchecked")
	@Override public void elementChanged(Object o) {
		int idx = indexOf(o);
		if (idx == -1) return;
		int newPos = findPosition((E) o);
		if (newPos == idx) return;
		super.move(idx,newPos);
		super.elementChanged(o);
	}
	
	@SuppressWarnings("unchecked")
	@Override public boolean add(E o) {
		super.add(findPosition(o), o);
		return true;
	}
	
	@SuppressWarnings("unchecked")
	@Override public int indexOf(Object o) {
		if (size() < 5) return super.indexOf(o);
		return binarySearch((E) o);
	}
	
	@SuppressWarnings("unchecked")
	private int binarySearch(E o) {
		int low = 0, high = size(), mid;
		while (low < high - 1) {
			mid = (low + high)/2;
			if (o.compareTo((E) super.get(mid)) >= 0) {
				low = mid;
			}
			else {
				high = mid - 1;
			}
		}
		if (o.equals(super.get(low))) {
			return low;
		} else if (size() != high && o.equals(super.get(high))) {
			return high;
		}
		
		return -1;
	}
	
	@Override public void move(int oldPos, int newPos) { throw new UnsupportedOperationException(); }
	
	private int findPosition(Comparable<E> o) {
		int low = 0, high = size(), mid;
		while (low != high) {
			mid = (low + high)/2;
			if (o.compareTo((E) super.get(mid)) >= 0) {
				low = mid + 1;
			} else {
				high = mid;
			}
		}
		return low;
	}
	
	/***
	 * Adds objects matching search in list
	 * !!! This method should only be run on lists with objects inheriting from Base !!!
	 * @param list
	 * @param search
	 */
	public void getMatch(List<E> list, Search search) {
		for (int i = 0; i < size(); i++) {
			if (search.matches((Base) get(i))) {
				list.add(get(i));
			}
		}
	}
	
}